home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / C / LIB / UNIXLIB37B / !UnixLib37 / src / unix / c / tty < prev    next >
Text File  |  1996-11-09  |  17KB  |  876 lines

  1. /****************************************************************************
  2.  *
  3.  * $Source: /unixb/home/unixlib/source/unixlib37/src/unix/c/RCS/tty,v $
  4.  * $Date: 1996/11/06 22:01:42 $
  5.  * $Revision: 1.5 $
  6.  * $State: Rel $
  7.  * $Author: unixlib $
  8.  *
  9.  * $Log: tty,v $
  10.  * Revision 1.5  1996/11/06 22:01:42  unixlib
  11.  * Yet more changes by NB, PB and SC.
  12.  *
  13.  * Revision 1.4  1996/10/30 22:04:51  unixlib
  14.  * Massive changes made by Nick Burret and Peter Burwood.
  15.  *
  16.  * Revision 1.3  1996/07/21 22:12:31  unixlib
  17.  * CL_0001 Nick Burret
  18.  * Improve memory handling. Remove C++ library incompatibilities.
  19.  * Improve file stat routines.
  20.  *
  21.  * Revision 1.2  1996/05/06 09:01:35  unixlib
  22.  * Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
  23.  * Saved for 3.7a release.
  24.  *
  25.  * Revision 1.1  1996/04/19 21:35:27  simon
  26.  * Initial revision
  27.  *
  28.  ***************************************************************************/
  29.  
  30. static const char rcs_id[] = "$Id: tty,v 1.5 1996/11/06 22:01:42 unixlib Rel $";
  31.  
  32. /* SYS V tty device driver for RiscOS */
  33.  
  34. #include <signal.h>
  35. #include <string.h>
  36. #include <ctype.h>
  37. #include <errno.h>
  38. #include <stdlib.h>
  39. #include <fcntl.h>
  40. #include <termio.h>
  41.  
  42. #include <sys/syslib.h>
  43. #include <sys/types.h>
  44. #include <sys/unix.h>
  45. #include <sys/dev.h>
  46. #include <sys/tty.h>
  47. #include <sys/os.h>
  48. #include <sys/param.h>
  49. #include <sys/swis.h>
  50.  
  51. static struct tty *__t;        /* current tty */
  52.  
  53. /* store the number of characters actually displayed for this single character
  54.    in the del buffer.  When a backspace/delete is processed, then we know
  55.    how many characters to rub out.  cx is a pointer to the current position
  56.    within the buffer and sx is the number of displayed characters on this line.
  57.    When a newline is written, cx and sx are reset to 0. */
  58.  
  59. #define __ttyx(x)    /* increment cursor posn. by (x) */ \
  60.     (__t->sx += (x), \
  61.     __t->del[__t->cx = (__t->cx + 1) & (MAX_INPUT - 1)] = (x))
  62.  
  63. static int __ttyicanon (void *buf, int nbyte, struct file *f);
  64. static int __ttyiraw (void *buf, int nbyte, struct file *f);
  65.  
  66. static int __ttyinput (int c, int iflag);
  67. static void __ttyecho (int c, int oflag, int lflag);
  68. static void __ttydel (int lflag);
  69. static void __ttytab (int oflag);
  70. static void __ttycr (int oflag);
  71. static void __ttynl (int oflag);
  72.  
  73. static char __ttybaud[0x10] =
  74. {0, 9, 1, 10, 11, 2, 0, 3, 12, 4, 13, 5, 6, 7, 8, 0};
  75.  
  76. /* get console window size */
  77.  
  78. static void
  79. __tty_console_gwinsz (register struct winsize *w)
  80. {
  81.   static int i[9] =
  82.   {132, 134, 135, 133, 128, 130, 129, 131, -1};
  83.   int o[8];
  84.   int r[10];
  85.  
  86.   r[0] = (int) i;
  87.   r[1] = (int) o;
  88.   os_swi (OS_ReadVduVariables, r);
  89.   w->ws_col = o[1] - o[0] + 1;
  90.   w->ws_row = o[3] - o[2] + 1;
  91.   w->ws_xpixel = o[5] - o[4] + 1;
  92.   w->ws_ypixel = o[7] - o[6] + 1;
  93. }
  94.  
  95. /* set console window size */
  96.  
  97. static void
  98. __tty_console_swinsz (register struct winsize *w)
  99. {
  100.   static int i[7] =
  101.   {132, 135, 128, 131, 4, 5, -1};
  102.   int o[6];
  103.   int r[10];
  104.   register int j;
  105.  
  106.   r[0] = (int) i;
  107.   r[1] = (int) o;
  108.   os_swi (OS_ReadVduVariables, r);
  109.   os_vdu (28);
  110.   os_vdu (o[0]);
  111.   os_vdu (o[1] + w->ws_row - 1);
  112.   os_vdu (o[0] + w->ws_col - 1);
  113.   os_vdu (o[1]);
  114.   os_vdu (24);
  115.   j = o[2];
  116.   j <<= o[4];
  117.   os_vdu (j & 0xff);
  118.   os_vdu (j >> 8);
  119.   j = o[3] - (w->ws_ypixel - 1);
  120.   j <<= o[5];
  121.   os_vdu (j & 0xff);
  122.   os_vdu (j >> 8);
  123.   j = o[2] + w->ws_xpixel - 1;
  124.   j <<= o[4];
  125.   os_vdu (j & 0xff);
  126.   os_vdu (j >> 8);
  127.   j = o[3];
  128.   j <<= o[5];
  129.   os_vdu (j & 0xff);
  130.   os_vdu (j >> 8);
  131. #ifdef SIGWINCH
  132.   /* Raise the 'Window size change' signal to notify any applications
  133.      that might be interested.  */
  134.   raise (SIGWINCH);
  135. #endif
  136. }
  137.  
  138. /* read console */
  139.  
  140. static void
  141. __tty_console_gterm (register struct termio *t)
  142. {
  143.   int r[3];
  144.  
  145.   os_byte (0xdc, 0, 0xff, r);
  146.   t->c_cc[VINTR] = r[1];
  147.   os_byte (0xe5, 0, 0xff, r);
  148.   if (r[1])
  149.     t->c_lflag &= ~ISIG;
  150.   else
  151.     t->c_lflag |= ISIG;
  152. }
  153.  
  154. /* set console */
  155.  
  156. static void
  157. __tty_console_sterm (register struct termio *t)
  158. {
  159.   os_byte (0xdc, t->c_cc[VINTR], 0, 0);
  160.   if (t->c_lflag & ISIG)
  161.     os_byte (0xe5, 0, 0, 0);
  162.   else
  163.     os_byte (0xe5, 0xff, 0, 0);
  164. }
  165.  
  166. /* set RS423 */
  167.  
  168. static void
  169. __tty_423_sterm (register struct termio *t)
  170. {
  171.   register int i, c;
  172.   int r[10];
  173.  
  174.   i = t->c_cflag & CIBAUD;
  175.   i = i ? (i >> IBSHIFT) : (t->c_cflag & CBAUD);
  176.   r[0] = 5;
  177.   if (r[1] = __ttybaud[i])
  178.     os_swi (OS_SerialOp, r);
  179.   i = t->c_cflag & CBAUD;
  180.   r[0] = 6;
  181.   if (r[1] = __ttybaud[i])
  182.     os_swi (OS_SerialOp, r);
  183.   i = t->c_cflag;
  184.   switch (i & CSIZE)
  185.     {
  186.     case CS5:
  187.       c = 3;
  188.       break;
  189.     case CS6:
  190.       c = 2;
  191.       break;
  192.     case CS7:
  193.       c = 1;
  194.       break;
  195.     case CS8:
  196.     default:
  197.       c = 0;
  198.       break;
  199.     }
  200.   if (i & CSTOPB)
  201.     c |= 0x04;
  202.   if (i & PARENB)
  203.     {
  204.       c |= 0x08;
  205.       if (!(i & PARODD))
  206.     c |= 0x10;
  207.     }
  208.   r[0] = 1;
  209.   r[1] = c;
  210.   os_swi (OS_SerialOp, r);
  211. }
  212.  
  213. int
  214. __ttyopen (char *file, int mode, struct file *f)
  215. {
  216.   struct tty *_t;
  217.   int l;
  218.  
  219.   mode = mode;
  220.  
  221.   switch (*(file + 5))
  222.     {
  223.     case 'c':            /* console */
  224.       _t = __u->tty + (l = TTY_CON);
  225.       __u->status.tty_type = TTY_CON;
  226.       break;
  227.     case 'r':            /* rs423 */
  228.       _t = __u->tty + (l = TTY_423);
  229.       __u->status.tty_type = TTY_423;
  230.       break;
  231.     case 't':            /* tty */
  232.       _t = __u->tty + (l = __u->status.tty_type);
  233.       break;
  234.     default:
  235.       return (-1);
  236.       break;
  237.     }
  238.  
  239.   {
  240.     register struct termio *t = _t->t;
  241.  
  242.     t->c_iflag = BRKINT | ICRNL | IMAXBEL;
  243.     t->c_oflag = OPOST | ONLCR | XTABS;
  244.     if (l == TTY_CON)
  245.       t->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
  246.     else if (l == TTY_423)
  247.       t->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
  248.     t->c_lflag = ISIG | ICANON | ECHO;
  249.     t->c_line = 0;
  250.  
  251.     {
  252.       static char cc[NCC] =
  253.       {CINTR, CQUIT, CERASE, CKILL, CEOF, CEOL, CEOL2,
  254.        CSWTCH, CSTART, CSTOP, CSUSP, 0, CREPRINT, CDISCARD, CWERASE, CLNEXT};
  255.  
  256.       memcpy (t->c_cc, cc, NCC);
  257.     }
  258.  
  259.     if (l == TTY_CON)
  260.       __tty_console_gterm (t);    /* RS423 is set up later */
  261.   }
  262.  
  263.   {
  264.     register struct winsize *w = _t->w;
  265.  
  266.     if (l == TTY_CON)
  267.       __tty_console_gwinsz (w);
  268.     else if (l == TTY_423)
  269.       {
  270.     w->ws_col = 80;
  271.     w->ws_row = 25;
  272.     w->ws_xpixel = w->ws_ypixel = 0;
  273.       }
  274.   }
  275.  
  276.   if (l == TTY_CON)
  277.     {
  278.       _t->out = os_vdu;
  279.       _t->in = os_get;
  280.       _t->scan = os_inkey;
  281.       _t->init = os_console;
  282.       _t->flush = os_keyflush;
  283.     }
  284.   else if (l == TTY_423)
  285.     {
  286.       _t->out = os_423vdu;
  287.       _t->in = os_423get;
  288.       _t->scan = os_423inkey;
  289.       _t->init = os_423;
  290.       _t->flush = os_423flush;
  291.     }
  292.  
  293. #ifndef __TTY_STATIC_BUFS
  294.   _t->buf = 0;
  295.   _t->del = 0;
  296. #endif
  297.   _t->ptr = _t->buf;
  298.   _t->cnt = 0;
  299.   _t->sx = _t->cx = 0;
  300.  
  301.   {
  302.     register int *r = f->r;
  303.  
  304.     r[0] = r[1] = r[2] = r[3] = r[4] = 0;
  305.     r[5] = 0x33;
  306.   }
  307.  
  308.   __funcall ((*(_t->init)), ());
  309.  
  310.   if (l == TTY_423)
  311.     __tty_423_sterm (_t->t);
  312.  
  313.   return (l);
  314. }
  315.  
  316. int
  317. __ttyclose (int l, struct file *f)
  318. {
  319.   register struct tty *_t;
  320.  
  321.   f = f;
  322.  
  323.   _t = __u->tty + l;
  324.  
  325. #ifndef __TTY_STATIC_BUFS
  326.   if ((unsigned char*)_t->del >= __lomem && (unsigned char*)_t->del < __break)
  327.     free (_t->del);
  328.   if ((unsigned char*)_t->buf >= __lomem && (unsigned char*)_t->buf < __break)
  329.     free (_t->buf);
  330.  
  331.   _t->buf = 0;
  332.   _t->del = 0;
  333. #endif
  334.  
  335.   _t->ptr = _t->buf;
  336.   _t->cnt = 0;
  337.   _t->sx = _t->cx = 0;
  338.  
  339.   return (0);
  340. }
  341.  
  342.  
  343. int
  344. __ttyread (int l, void *buf, int nbyte, struct file *f)
  345. {
  346.   __t = __u->tty + l;
  347.  
  348. #ifndef __TTY_STATIC_BUFS
  349.   if (!__t->del)
  350.     {
  351.       if (!(__t->del = malloc (MAX_INPUT)))
  352.         {
  353.         errno = ENOMEM;
  354.         return (-1);
  355.         }
  356.       __t->sx = __t->cx = 0;
  357.     }
  358. #endif
  359.  
  360.   return ((__t->t->c_lflag & ICANON) ? \
  361.       __ttyicanon (buf, nbyte, f) : \
  362.       __ttyiraw (buf, nbyte, f));
  363. }
  364.  
  365. static int
  366. __ttyicanon (void *buf, register int nbyte, struct file *f)
  367. {
  368.   register int c, i;
  369.   register char *s;
  370.   register int nflag;
  371.   register int iflag, oflag, lflag;
  372.   register char *cc;
  373.   int ceof, ceol, ceol2;
  374.  
  375. #define F_LNEXT     000001
  376. #define F_MAX        000002
  377. #define F_NDELAY    000004
  378.  
  379. #ifndef __TTY_STATIC_BUFS
  380.   if (!__t->buf)
  381.     {
  382.       if (!(__t->buf = malloc (MAX_INPUT)))
  383.     {
  384.       errno = ENOMEM;
  385.       return (-1);
  386.     }
  387.       __t->cnt = 0;
  388.       __t->ptr = __t->buf;
  389.     }
  390. #endif
  391.  
  392.   if (__t == __u->tty)
  393.     os_byte (0xe5, 0xff, 0, 0);    /* disable SIGINT */
  394.  
  395. ret:
  396.  
  397.   if (__t->cnt != 0)
  398.     {
  399.       if (__t == __u->tty)
  400.     os_byte (0xe5, 0, 0, 0);    /* re-enable SIGINT */
  401.  
  402.       i = (nbyte > __t->cnt) ? __t->cnt : nbyte;
  403.       memcpy (buf, __t->ptr, i);
  404.       __t->cnt -= i;
  405.       __t->ptr += i;
  406.       return (i);
  407.     }
  408.  
  409.   nflag = (f->oflag & O_NDELAY) ? F_NDELAY : 0;
  410.   iflag = __t->t->c_iflag;
  411.   oflag = __t->t->c_oflag;
  412.   lflag = __t->t->c_lflag;
  413.   cc = (char *) __t->t->c_cc;
  414.  
  415.   ceof = cc[VEOF];
  416.   if (!(ceol = cc[VEOL]))
  417.     ceol--;
  418.   if (!(ceol2 = cc[VEOL2]))
  419.     ceol2--;
  420.  
  421.   s = __t->ptr = __t->buf;
  422.   __t->sx = __t->cx = 0;
  423.   i = 0;
  424.  
  425.   for (;;)
  426.     {
  427.       if (i < MAX_INPUT)
  428.     nflag &= ~F_MAX;
  429.       else
  430.     nflag |= F_MAX;
  431.       if (nflag & F_NDELAY)
  432.     c = __funcall ((*(__t->scan)), (0));
  433.       else
  434.     c = __funcall ((*(__t->in)), ());
  435.       if (c < 0)
  436.     goto eol;
  437.       if (c == '\r' && iflag & IGNCR)
  438.     continue;
  439.       c = __ttyinput (c, iflag);
  440.       if (!(nflag & F_LNEXT))
  441.     {
  442.       if (c == '\n' || c == ceof || c == ceol || c == ceol2)
  443.         goto eol;
  444.       if (c == cc[VLNEXT])
  445.         {
  446.           nflag |= F_LNEXT;
  447.           continue;
  448.         }
  449.       if (c == cc[VERASE])
  450.         {
  451.           if (i)
  452.         {
  453.           __ttydel (lflag);
  454.           i--;
  455.         }
  456.           continue;
  457.         }
  458.       if (c == cc[VWERASE])
  459.         {
  460.           while (--i >= 0 && isspace (s[i]))
  461.         __ttydel (lflag);
  462.           i++;
  463.           while (--i >= 0 && !isspace (s[i]))
  464.         __ttydel (lflag);
  465.           i++;
  466.           continue;
  467.         }
  468.       if (c == cc[VKILL])
  469.         {
  470.           while (--i >= 0)
  471.         __ttydel (lflag);
  472.           i++;
  473.           if (lflag & ECHOK)
  474.         __ttynl (oflag);
  475.           continue;
  476.         }
  477.       if (c == cc[VREPRINT])
  478.         {
  479.           register int j;
  480.           __ttyecho (c, oflag, lflag);
  481.           __ttynl (oflag);
  482.           if (!(oflag & ONLRET))
  483.         __ttycr (oflag);
  484.           for (j = 0; j < i; j++)
  485.         __ttyecho (s[j], oflag, lflag);
  486.           continue;
  487.         }
  488.       if (lflag & ISIG)
  489.         {
  490.           if (c == cc[VINTR])
  491.         {
  492.           raise (SIGINT);
  493.           continue;
  494.         }
  495.           if (c == cc[VQUIT])
  496.         {
  497.           raise (SIGQUIT);
  498.           continue;
  499.         }
  500.         }
  501.     }
  502.       else
  503.     nflag &= ~F_LNEXT;
  504.       if (nflag & F_MAX)
  505.     {
  506.       if (iflag & IMAXBEL)
  507.         __funcall ((*(__t->out)), ('\007'));
  508.     }
  509.       else
  510.     {
  511.       __ttyecho (c, oflag, lflag);
  512.       s[i++] = c;
  513.     }
  514.     }
  515.  
  516. eol:
  517.  
  518.   if (c != cc[VEOF] && c >= 0)
  519.     {
  520.       if (!(nflag & F_MAX))
  521.     {
  522.       __ttyecho (c, oflag, lflag);
  523.       s[i++] = c;
  524.     }
  525.     }
  526.  
  527.   if (__t->cnt = i)
  528.     goto ret;
  529.   else
  530.     {
  531.       if (__t == __u->tty)
  532.     os_byte (0xe5, 0, 0, 0);    /* re-enable SIGINT */
  533.  
  534.       return (0);
  535.     }
  536.  
  537. #undef F_LNEXT
  538. #undef F_MAX
  539. #undef F_NDELAY
  540. }
  541.  
  542. static int
  543. __ttyiraw (void *buf, register int nbyte, struct file *f)
  544. {
  545.   register int c, i;
  546.   register char *s;
  547.   register int nflag;
  548.   register int iflag, oflag, lflag;
  549.   register char *cc;
  550.   register unsigned int vm, vt;
  551.  
  552. #define F_NSCAN     000001
  553.  
  554.   nflag = 0;
  555.   iflag = __t->t->c_iflag;
  556.   oflag = __t->t->c_oflag;
  557.   lflag = __t->t->c_lflag;
  558.   cc = (char *) __t->t->c_cc;
  559.  
  560.   if (f->oflag & O_NDELAY)
  561.     vm = vt = 0;
  562.   else
  563.     {
  564.       vm = (cc[VMIN] && cc[VTIME]) ? 1 : cc[VMIN];
  565.       vt = cc[VTIME] * 10;
  566.     }
  567.   if (cc[VMIN] && !cc[VTIME])
  568.     nbyte = vm, nflag |= F_NSCAN;
  569.  
  570.   s = buf;
  571.   i = 0;
  572.  
  573.   while (i < nbyte)
  574.     {
  575.       if (nflag & F_NSCAN)
  576.     c = __funcall ((*(__t->in)), ());
  577.       else
  578.     c = __funcall ((*(__t->scan)), (vt));
  579.       if (c < 0)
  580.     {
  581.       if (i >= vm)
  582.         return (i);
  583.       else
  584.         continue;
  585.     }
  586.       if (c == '\r' && iflag & IGNCR)
  587.     continue;
  588.       c = __ttyinput (c, iflag);
  589.       if (lflag & ISIG)
  590.     {
  591.       if (c == cc[VINTR] && __t != __u->tty)
  592.         {
  593.           raise (SIGINT);
  594.           continue;
  595.         }
  596.       if (c == cc[VQUIT])
  597.         {
  598.           raise (SIGQUIT);
  599.           continue;
  600.         }
  601.     }
  602.       __ttyecho (c, oflag, lflag);
  603.       s[i++] = c;
  604.     }
  605.  
  606.   return (i);
  607.  
  608. #undef F_NSCAN
  609. }
  610.  
  611.  
  612. int
  613. __ttywrite (int l, void *buf, int nbyte, struct file *f)
  614. {
  615.   register int i, c;
  616.   register char *s;
  617.   register int oflag, lflag;
  618.   register char *cc;
  619.   register int (*out) (int);
  620.  
  621.   f = f;
  622.  
  623.   __t = __u->tty + l;
  624.  
  625. #ifndef __TTY_STATIC_BUFS
  626.   if (!__t->del)
  627.     {
  628.       if (!(__t->del = malloc (MAX_INPUT)))
  629.         {
  630.         errno = ENOMEM;
  631.         return (-1);
  632.         }
  633.       __t->sx = __t->cx = 0;
  634.     }
  635. #endif
  636.  
  637.   oflag = __t->t->c_oflag;
  638.   lflag = __t->t->c_lflag;
  639.   cc = (char *) __t->t->c_cc;
  640.   out = __t->out;
  641.  
  642.   s = buf;
  643.   i = 0;
  644.  
  645.   while (i < nbyte)
  646.     {
  647.       c = s[i++];
  648.       if ((oflag & (OPOST | OLCUC)) == (OPOST | OLCUC))
  649.     if (isupper (c))
  650.       c = _tolower (c);
  651.       if (c == cc[VERASE])
  652.     __ttydel (lflag);
  653.       else if (c == '\t')
  654.     __ttytab (oflag);
  655.       else if (c == '\n')
  656.     __ttynl (oflag);
  657.       else if (c == '\r')
  658.     __ttycr (oflag);
  659.       else
  660.     {
  661.       __ttyx (1);
  662.       __funcall ((*out), (c));
  663.     }
  664.     }
  665.  
  666.   return (nbyte);
  667. }
  668.  
  669.  
  670. static int
  671. __ttyinput (register int c, register int iflag)
  672. {
  673.   if (iflag & ISTRIP)
  674.     c &= 0x7f;
  675.   if (iflag & IUCLC)
  676.     if (isupper (c))
  677.       c += ('a' - 'A');
  678.   if (iflag & INLCR)
  679.     if (c == '\n')
  680.       c = '\r';
  681.   if (iflag & ICRNL)
  682.     if (c == '\r')
  683.       c = '\n';
  684.   return (c);
  685. }
  686.  
  687. static void
  688. __ttyecho (register int c, register int oflag, register int lflag)
  689. {
  690.   if (!((lflag & ECHO) || ((c == '\n') && (lflag & ECHONL))))
  691.     return;
  692.  
  693.   if (c == '\t')
  694.     __ttytab (oflag);
  695.   else if (c == '\n')
  696.     __ttynl (oflag);
  697.   else if (c == '\r')
  698.     __ttycr (oflag);
  699.   else if (iscntrl (c))
  700.     {
  701.       __ttyx (2);
  702.       __funcall ((*(__t->out)), ('^'));
  703.       __funcall ((*(__t->out)), ((c == 0x7f) ? '?' : (c + '@')));
  704.     }
  705.   else
  706.     {
  707.       __ttyx (1);
  708.       __funcall ((*(__t->out)), (c));
  709.     }
  710. }
  711.  
  712. static void
  713. __ttydel (register int lflag)
  714. {
  715.   register int x;
  716.  
  717. #ifndef __TTY_STATIC_BUFS
  718.   /* this should be impossible since the call path to this static function
  719.      should have already checked __t->del.  */
  720.   if (!__t->del)
  721.     {
  722.       if (!(__t->del = malloc (MAX_INPUT)))
  723.         {
  724.         errno = ENOMEM;
  725.         return;
  726.         }
  727.       __t->sx = __t->cx = 0;
  728.     }
  729. #endif
  730.  
  731.   if (__t->sx)
  732.     {
  733.       x = __t->del[__t->cx];
  734.       __t->cx = (__t->cx - 1) & (MAX_INPUT - 1);
  735.     }
  736.   else
  737.     x = 1;
  738.  
  739.   __t->sx = (__t->sx > x) ? (__t->sx - x) : 0;
  740.  
  741.   if (lflag & ECHO)
  742.     {
  743.       if (lflag & ECHOE)
  744.     while (x--)
  745.       {
  746.         __funcall ((*(__t->out)), ('\b'));
  747.         __funcall ((*(__t->out)), (' '));
  748.         __funcall ((*(__t->out)), ('\b'));
  749.       }
  750.       else
  751.     while (x--)
  752.       __funcall ((*(__t->out)), ('\177'));
  753.     }
  754. }
  755.  
  756. static void
  757. __ttytab (register int oflag)
  758. {
  759.   if ((oflag & (OPOST | XTABS)) == (OPOST | XTABS))
  760.     {
  761.       register int x;
  762.  
  763.       x = (8 - (__t->sx & 0x7));
  764.       __ttyx (x);
  765.       while (x--)
  766.     __funcall ((*(__t->out)), (' '));
  767.     }
  768.   else
  769.     {
  770.       __ttyx (1);
  771.       __funcall ((*(__t->out)), ('\t'));
  772.     }
  773. }
  774.  
  775. static void
  776. __ttycr (register int oflag)
  777. {
  778.   __t->sx = 0;
  779.   if ((oflag & (OPOST | OCRNL)) == (OPOST | OCRNL))
  780.     __funcall ((*(__t->out)), ('\n'));
  781.   else if ((oflag & (OPOST | ONOCR)) != (OPOST | ONOCR))
  782.     __funcall ((*(__t->out)), ('\r'));
  783. }
  784.  
  785. static void
  786. __ttynl (register int oflag)
  787. {
  788.   if (oflag & OPOST)
  789.     {
  790.       if (oflag & ONLCR)
  791.     if (__t->sx || !(oflag & ONOCR))
  792.       __funcall ((*(__t->out)), ('\r'));
  793.       if (oflag & (ONLCR | ONLRET))
  794.     __t->sx = 0;
  795.     }
  796.   __funcall ((*(__t->out)), ('\n'));
  797. }
  798.  
  799.  
  800. long
  801. __ttylseek (int l, long lpos, int whence, struct file *f)
  802. {
  803.   l = l;
  804.   lpos = lpos;
  805.   whence = whence;
  806.   f = f;
  807.   errno = ESPIPE;
  808.   return (-1);
  809. }
  810.  
  811.  
  812. int
  813. __ttyioctl (int l, int request, void *arg, struct file *f)
  814. {
  815.   register struct tty *_t = __u->tty + l;
  816.  
  817.   f = f;
  818.  
  819.   if (request == TIOCGWINSZ || request == TIOCSWINSZ)
  820.     {
  821.       register struct winsize *w = _t->w;
  822.  
  823.       if (request == TIOCGWINSZ)
  824.     {
  825.       if (l == TTY_CON)
  826.         __tty_console_gwinsz (w);
  827.       memcpy (arg, w, sizeof (struct winsize));
  828.     }
  829.       else
  830.     {
  831.       memcpy (w, arg, sizeof (struct winsize));
  832.       if (l == TTY_CON)
  833.         __tty_console_swinsz (w);
  834.     }
  835.     }
  836.   else
  837.     {
  838.       register struct termio *t = _t->t;
  839.  
  840.       if (request & TCDRAIN)
  841.     {
  842.       _t->ptr = _t->buf;
  843.       _t->cnt = 0;
  844.       __funcall ((*(_t->flush)), ());
  845.     }
  846.  
  847.       switch (request & ~TCDRAIN)
  848.     {
  849.     case TCGETA:
  850.       if (l == TTY_CON)
  851.         __tty_console_gterm (t);
  852.       memcpy (arg, t, sizeof (struct termio));
  853.       break;
  854.     case TCSETA:
  855.       memcpy (t, arg, sizeof (struct termio));
  856.       if (l == TTY_CON)
  857.         __tty_console_sterm (t);
  858.       else if (l == TTY_423)
  859.         __tty_423_sterm (t);
  860.       break;
  861.     case TCSBRK:
  862.       if (l == TTY_423 && !arg)
  863.         os_423break (25);
  864.       break;
  865.     case 0:
  866.       break;
  867.     default:
  868.       errno = EINVAL;
  869.       return (-1);
  870.       break;
  871.     }
  872.     }
  873.  
  874.   return (0);
  875. }
  876.